#!/usr/bin/env python
# _*_coding:utf-8 _*_
__author__ = "Gao"
from django import template
from django.utils.safestring import mark_safe
from django.utils import timezone
from django.utils.timezone import datetime
from django.utils.timezone import timedelta
from django.core.exceptions import FieldDoesNotExist


register = template.Library()

@register.simple_tag
def render_model_name(admin_class):
    '''返回model名'''
    return admin_class.model._meta.verbose_name_plural    # 返回自定义显示名


@register.simple_tag
def get_query_set(admin_class):
    '''返回Model所有数据'''
    return admin_class.model.objects.all()


@register.simple_tag
def render_obj_data(request, obj, admin_class):
    '''根据定制化Admin,渲染每列数据'''
    temp = []
    td_tag = '<td>{column_data}</td>'
    for index,column in enumerate(admin_class.list_display):
        try:
            field_obj = obj._meta.get_field(column)    # 根据字段名获取相应属性
            if field_obj.choices:    # 判断属性是否是choices类型
                column_data = getattr(obj,'get_%s_display'%column)()
            else:
                column_data = getattr(obj, column)
            if type(column_data).__name__ == 'datetime':
                column_data = timezone.localtime(column_data)    # 手动进行时区转换
                column_data = column_data.strftime("%Y-%m-%d %H:%M:%S")
        except FieldDoesNotExist:
            # 判断是否是Admin中添加的字段:
            if hasattr(admin_class, column):
                admin_class.instance = obj    # 向Admin传入当前请求信息
                admin_class.request = request
                column_data = getattr(admin_class, column)()
            else:
                raise FieldDoesNotExist('需要显示的字段不存在')
        if index == 0:
            column_data = '<a href={request_path}/{nid}/change/>{data}</a>'\
                .format(request_path=request.path_info,nid=obj.id,data=column_data)
        temp.append(td_tag.format(column_data=column_data))

    res_str = ''.join(temp)
    return mark_safe(res_str)


@register.simple_tag
def render_page_btns(query_set, conditions, privious_orderby_key, search_text):
    # 渲染分页按钮
    page_list = []
    if privious_orderby_key:
        order_by = '&o=%s'% privious_orderby_key
    else:
        order_by = ''
    if search_text:
        search = '&_q=%s'% search_text
    else:
        search = ''

    conditions_str = get_conditions_str(conditions)
    page_num = 5    # 导航栏显示5页
    if query_set.paginator.num_pages <= page_num:    # 总页数小于等于3
        start_index = 1
        end_index = query_set.paginator.num_pages + 1
    else:
        if query_set.number <= (page_num +1 )/2:
            start_index = 1
            end_index = start_index + page_num
        else:
            if (query_set.number + (page_num - 1)/2) > query_set.paginator.num_pages:
                end_index = query_set.paginator.num_pages + 1
                start_index = query_set.paginator.num_pages - (page_num -1)
            else:
                start_index = query_set.number - (page_num - 1)/2
                end_index = query_set.number + (page_num + 1)/2

    # 显示第一页
    if query_set.number > (page_num + 1 )/2:
        first_page = '<li><a href="?page=%s%s%s%s">%s</a></li>'%(1,conditions_str, order_by,search, 1)
        page_list.append(first_page)
        page_list.append('<li><a href="javascript:void(0);">...</a></li>')

    # 显示中间的页数

    for i in range(int(start_index), int(end_index)):
        ele_class = ''
        if i == query_set.number:
            ele_class = 'active'
        page = '<li class="%s"><a href="?page=%s%s%s%s">%s</a></li>'%(ele_class,i,conditions_str,order_by,search, i)
        page_list.append(page)


    if query_set.number <= (query_set.paginator.num_pages - (page_num +1)/2):
        # 显示最后一页
        last_page = '<li><a href="?page=%s%s%s%s">%s</a></li>'\
                    %(query_set.paginator.num_pages,conditions_str, order_by,search, query_set.paginator.num_pages)
        page_list.append('<li><a href="#">...</a></li>')
        page_list.append(last_page)
    page_str = mark_safe(''.join(page_list))

    return page_str


@register.simple_tag
def render_thead_column(admin_class,column, orderby_key, conditions, page, search_text):
    '''渲染表头，添加排序功能'''
    try :
        field = admin_class.model._meta.get_field(column)
    except FieldDoesNotExist:
        # 判断是否是Admin中添加的字段
        if hasattr(admin_class, column):
            field = getattr(admin_class, column)
            column_verbose_name = field.verbose_name if hasattr(field, 'verbose_name') else column.upper()
            ele='''<th><a href=#>{column_verbose_name}</a></th>'''.format(column_verbose_name=column_verbose_name)
        else:
            raise FieldDoesNotExist('需要显示的字段不存在')
    else:
        ele = '''<th><a href="?{page}o={orderby_key}{conditions}{search}">{column}{sort_icon}</a></th>'''
        if page:
            page_str = 'page=%s&'%page
        else:
            page_str = ''
        if search_text:
            search = '&_q=%s' % search_text
        else:
            search = ''

        if orderby_key and orderby_key.strip('-') == column:
            if orderby_key.startswith('-'):
                sort_icon = '<span class="glyphicon glyphicon-chevron-up"></span>'
            else:
                sort_icon = '<span class="glyphicon glyphicon-chevron-down"></span>'
            orderby_key = orderby_key
        else:
            orderby_key = column
            sort_icon = ''

        conditions_str = get_conditions_str(conditions)
        column = field.verbose_name or column
        ele = ele.format(page=page_str, orderby_key=orderby_key, conditions=conditions_str,search=search, column=column, sort_icon=sort_icon)
    return mark_safe(ele)


@register.simple_tag
def render_page_previous(query_set, conditions, privious_orderby_key, search_text):
    '''显示上一页按钮'''
    if privious_orderby_key:
        order_by = '&o=%s'% privious_orderby_key
    else:
        order_by = ''
    if search_text:
        search = '&_q=%s'% search_text
    else:
        search = ''
    conditions_str = get_conditions_str(conditions)
    ele = '<li><a href="?page=%s%s%s%s">&laquo;</a></li>'%(query_set.previous_page_number(),conditions_str, order_by, search)
    return mark_safe(ele)


@register.simple_tag
def render_page_next(query_set, conditions, privious_orderby_key, search_text):
    '''显示下一页按钮'''
    conditions_str = get_conditions_str(conditions)
    if privious_orderby_key:
        order_by = '&o=%s'% privious_orderby_key
    else:
        order_by = ''
    if search_text:
        search = '&_q=%s' % search_text
    else:
        search = ''
    ele = '<li><a href="?page=%s%s%s%s">&raquo;</a></li>'%(query_set.next_page_number(),conditions_str, order_by, search)
    return mark_safe(ele)


@register.simple_tag
def render_filter_ele(current_condition, admin_class, conditions):
    '''
    显示自定义过滤条件
    Attribute:
        current_condition: 当前filter字段
        admin_class: 自定义的admin_class
        conditions: 上一次提交的过滤条件
    '''
    select_tag = '<select class="form-control" name="{filter_key}"><option value=''>----</option>'
    field_obj = admin_class.model._meta.get_field(current_condition[0])

    if type(field_obj).__name__ in ['DateField', 'DateTimeField']:
        filter_key = '%s__gte'%current_condition[0]
        date_filter = []
        tody = datetime.now().date()    # 获取当前日期
        date_filter.append(('今天',tody))
        date_filter.append(('昨天', tody - timedelta(days=1)))
        date_filter.append(('近7天', tody - timedelta(days=7)))
        date_filter.append(('本月', tody.replace(day=1)))
        date_filter.append(('近1个月', tody - timedelta(days=30)))
        date_filter.append(('近3个月', tody - timedelta(days=90)))
        date_filter.append(('近半年', tody - timedelta(days=180)))
        date_filter.append(('本年', tody - tody.replace(month=1, day=1)))
        date_filter.append(('近1年', tody - timedelta(days=365)))

        for select_item in date_filter:
            selected = ''
            if conditions.get(current_condition[0]+'__gte') == str(select_item[1]):
                selected = 'selected'
            select_tag += '<option %s value="%s">%s</option>' % (selected, select_item[1], select_item[0])

    else:
        filter_key = current_condition[0]
        choice_list = []
        if field_obj.choices:
            choice_list = field_obj.choices    # 判断是否是内存choices
        if type(field_obj).__name__ == 'ForeignKey':
            choice_list = field_obj.get_choices()[1:]    # 如果是外键，获取关联表中的所有数据
        for choice_item in choice_list:
            selected = ''
            if conditions.get(current_condition) == str(choice_item[0]):
                selected = 'selected'
            select_tag += '<option %s value="%s">%s</option>'%(selected,choice_item[0], choice_item[1])

    select_tag += '</select>'
    select_tag = select_tag.format(filter_key=filter_key)
    return mark_safe(select_tag)


@register.simple_tag
def render_standby_items(form_obj,admin_class, field):
    '''
    返回待选的选项
    Attributes:
        admin_class:
        field: 当前循环的model_form字段
    '''
    model_field_obj = getattr(admin_class.model, field.name)
    all_items = model_field_obj.rel.model.objects.all()    # 获取所有可选项

    # 判断是否是添加操作
    if not form_obj.instance.id:
        return all_items
    else:
        obj_field_obj = getattr(form_obj.instance, field.name)
        selected_items = obj_field_obj.all()    # 获取已选项

        standby_items = []
        for item in all_items:
            if item not in selected_items:
                standby_items.append(item)

        return standby_items


@register.simple_tag
def render_selected_items(form_obj, field):
    '''
    返回已选的数据
    Attributes:
        form_obj:
        field: 当前循环的model_form字段
    '''

    # 判断是否是添加操作
    if not form_obj.instance.id:
        return []
    else:
        field_obj = getattr(form_obj.instance, field.name)
        return field_obj.all()


@register.simple_tag
def render_placeholder(search_fields):
    '''渲染placeholder'''
    text = []
    for search_field in search_fields:
        temp = search_field[-1] + ','
        text.append(temp)
        
    text = ''.join(text)
    return mark_safe(text)


@register.simple_tag
def render_delete_ids(objs):
    '''获取需要删除数据的id'''
    select_ids = []

    if 'QuerySet' in objs.__repr__():
        for obj in objs:
            select_ids.append(str(obj.id))
    else:
        select_ids.append(str(objs.id))

    val = ','.join(select_ids)
    input_ele = '<input name="ids" type="hidden" value="%s"/>'%val
    return mark_safe(input_ele)


@register.simple_tag
def render_action_name(admin_class,action):
    '''显示自定义action名字'''
    action_func = getattr(admin_class, action)

    return action_func.verbose_name if hasattr(action_func, 'verbose_name') else action


@register.simple_tag
def render_all_related_objs(objs):
    '''列出所有与被删除对象关联的记录'''

    res = []
    if 'QuerySet' in objs.__repr__():
        for obj in objs:
            # model_class =obj._meta.model
            # model_name = obj._meta.model_name
            temp = mark_safe(recursive_related_objs_lookup(obj))
            res.append(temp)

    else:
        temp = mark_safe(recursive_related_objs_lookup(objs))
        res.append(temp)
    res_str = ''.join(res)
    return mark_safe(res_str)


def recursive_related_objs_lookup(obj):
    '''递归查找与对象相关联的所有记录'''
    ul_ele = '<ul>'
    # li_ele = '<li> %s: %s</li>' % (obj._meta.verbose_name_plural, obj.__str__().strip('<>'))
    li_ele = '<li> %s: %s</li>'%(obj._meta.verbose_name_plural, obj.__str__())
    ul_ele += li_ele

    # 递归多对多字段(正向)
    sub_m2m_ele = ''
    for m2m_field in obj._meta.local_many_to_many:
        m2m_field_obj = getattr(obj, m2m_field.name)    # 获取多对多字段
        if m2m_field_obj.count() > 0:
            sub_m2m_ele += '<ul>'
            li_ele = '<li>%s:</li>' % m2m_field.verbose_name
            sub_m2m_ele += li_ele

            sub_m2m_ele += '<ul>'
            # 获取多对多关联记录
            for related_obj in m2m_field_obj.all():
                li_ele = '<li>%s</li>' %(related_obj.__str__())
                sub_m2m_ele += li_ele
            sub_m2m_ele += '</ul>'
            sub_m2m_ele += '</ul>'
    ul_ele+= sub_m2m_ele

    # 递归多对一字段
    for related_field in obj._meta.related_objects:
        # 多对多反查字段
        if 'ManyToManyRel' in related_field.__repr__():
            sub_m2m_ele = ''
            if hasattr(obj, related_field.get_accessor_name()):    # fieldname_set
                related_field_obj = getattr(obj, related_field.get_accessor_name())
                if related_field_obj.count()>0:
                    sub_m2m_ele += '<ul>'
                    li_ele = '<li>%s:</li>'%related_field_obj.model._meta.verbose_name_plural
                    sub_m2m_ele += li_ele
                    sub_m2m_ele += '<ul>'
                    related_objs = related_field_obj.all()
                    for related_obj in related_objs:
                        li_ele = '<li>%s</li>' % (related_obj.__str__())
                        sub_m2m_ele += li_ele
                    sub_m2m_ele += '</ul>'
                    sub_m2m_ele += '</ul>'
                    pass
            ul_ele +=sub_m2m_ele

        elif hasattr(obj, related_field.get_accessor_name()):
            related_field_obj = getattr(obj, related_field.get_accessor_name())

            if hasattr(related_field_obj,'all'):
                related_objs = related_field_obj.all()    # 多对一关联记录
            else:
                related_objs = [related_field_obj,]    # 一对一关联记录

            if len(related_objs) > 0:
                for o in related_objs:
                    node = recursive_related_objs_lookup(o)    # 递归查询关联记录
                    ul_ele += node

    ul_ele +='</ul>'
    return ul_ele
        


def get_conditions_str(conditions):
    '''获取上一次提交的过滤条件及排序规则，拼接Url'''
    conditons_list = []  # 获取上次提交的过滤条件
    for k, v in conditions.items():
        tmp_str = '&%s=%s' % (k, v)
        conditons_list.append(tmp_str)
    conditions_str = ''.join(conditons_list)
    return conditions_str